package com.icss.flow.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.icss.flow.mapper.DynamicTableMapper;
import com.icss.flow.pojo.entity.TMetaEntity;
import com.icss.flow.pojo.entity.TMetaField;
import com.icss.flow.enums.FieldTypeEnum;
import com.icss.flow.pojo.dto.TMetaEntityDTO;
import com.icss.flow.service.DynamicService;
import com.icss.flow.service.TMetaEntityService;
import com.icss.flow.service.TMetaFieldService;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.*;
import java.util.stream.Collectors;

@Service("dynamicService")
public class DynamicServiceImpl implements DynamicService {
    @Autowired
    private TMetaFieldService tMetaFieldService;

    @Autowired
    private TMetaEntityService tMetaEntityService;

    @Autowired
    private DynamicTableMapper dynamicTableMapper;

    @Transactional
    @Override
    public Boolean addFieldAndTable(String json) {
        TMetaEntityDTO tMetaEntityDTO = this.analysisJsonMap(json);
        TMetaEntity tMetaEntity = new TMetaEntity();
        //1.元数据实体更新entityJson
        BeanUtils.copyProperties(tMetaEntityDTO, tMetaEntity);
        tMetaEntityService.updateById(tMetaEntity);

        //获取历史元数据字段数据列表
        List<TMetaField> tMetaFieldList = tMetaEntityDTO.getFieldList();
        LambdaQueryWrapper<TMetaField> lqw = new LambdaQueryWrapper<>();
        lqw.eq(TMetaField::getEntityCode, tMetaEntityDTO.getEntityCode());
        List<TMetaField> oldTMetaFieldList=tMetaFieldService.list(lqw);
        Set<String> fieldNameSet=tMetaFieldList.stream()
                .map(TMetaField::getName)
                .collect(Collectors.toSet());
        Set<String> oldFieldNameSet = oldTMetaFieldList.stream()
                .map(TMetaField::getName)
                .collect(Collectors.toSet());
        //生成表名
        String tableName = tMetaEntityDTO.getPhysicalName();
        //3.根据表数据修改表结构或者生成表
        String tableId = tMetaEntityDTO.getName().toLowerCase() + "Id";

        tMetaFieldList.forEach(t -> {
            //枚举动态解析字段所属类型
            t.setTypeSql(FieldTypeEnum.getType(t.getType()).getFieldTypeSql());
        });
        //2.根据标识符当前实体状态 是否是第一次添加 true（修改字段类型，新增字段，删除字段）
        if (!tMetaEntityDTO.getCreateFlag()) {
            List<TMetaField> addTmetaFieldList = new ArrayList<>();
            List<TMetaField> deleteTmetaFieldList = new ArrayList<>();
            for (TMetaField tMetaField : tMetaFieldList) {
                // 如果新列表中的字段不在旧列表的字段名集合中，则是新增字段
                if (!oldFieldNameSet.contains(tMetaField.getName())) {
                    addTmetaFieldList.add(tMetaField);
                }
                for (TMetaField oldTmetaField : oldTMetaFieldList) {
                    //根据历史数据赋值修改后的字段 -autoId
                    if (oldTmetaField.getName().equals(tMetaField.getName())) {
                        tMetaField.setAutoId(oldTmetaField.getAutoId());
                    }
                    //对比历史数据类型结构 枚举动态解析膝盖后的字段所属类型
                    if(tMetaField.getName().equals(oldTmetaField.getName())&&tMetaField.getLabel().equals(oldTmetaField.getLabel())){
                        tMetaField.setOldTypeSql(FieldTypeEnum.getType(oldTmetaField.getType()).getFieldTypeSql());
                    }

                }
            }
            //如果旧列表中不存在新列表中的字段名，则需要删除中的字段名，则是删除字段
            for (TMetaField oldTmetaField : oldTMetaFieldList) {
                if (!fieldNameSet.contains(oldTmetaField.getName())) {
                    deleteTmetaFieldList.add(oldTmetaField);
                }
            }
            //新增字段
            if(ObjectUtils.isNotEmpty(addTmetaFieldList)){
                tMetaFieldService.saveBatch(addTmetaFieldList);
                dynamicTableMapper.appendEntityField(tableName,addTmetaFieldList);
            }
            //删除字段
            if(ObjectUtils.isNotEmpty(deleteTmetaFieldList)){
                tMetaFieldService.removeBatchByIds(deleteTmetaFieldList);
            //  dynamicTableDao.deleteEntityField(tableName,deleteTmetaFieldList);
            }
            //更新字段表
            tMetaFieldService.updateBatchById(tMetaFieldList);
            //修改表结构
            dynamicTableMapper.alterEntityTable(tableName,tMetaFieldList);

        }else {

            tMetaFieldService.saveBatch(tMetaFieldList);
            //新增-生成表
            dynamicTableMapper.generateEntityTable(tableName, tableId, tMetaFieldList);

        }

        return true;
    }

    @Override
    public Boolean updateFieldAndTable(String json) {
        return null;
    }

    @Override
    public Boolean deleteFieldAndTable(String json) {
        return null;
    }

    /***
     * 解析json
     * @param json
     * @return
     */
    public TMetaEntityDTO analysisJsonMap(String json) {
        TMetaEntityDTO tMetaEntityDTO = new TMetaEntityDTO();
        Gson gson = new Gson();
        JsonObject rootJson = gson.fromJson(json, JsonObject.class);
        // 获取widgetList数组
        JsonArray widgetList = rootJson.getAsJsonArray("widgetList");

        //获取entityCode
        Integer entityCode = rootJson.get("entityCode").getAsInt();
        LambdaQueryWrapper<TMetaEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TMetaEntity::getEntityCode, entityCode);
        TMetaEntity tMetaEntity = tMetaEntityService.getOne(queryWrapper);
        //表示已经创建的表单 已有元数据历则进行删除
        if (StringUtils.isEmpty(tMetaEntity.getEntityJson())) {
            LambdaQueryWrapper<TMetaField> lqw = new LambdaQueryWrapper<>();
            lqw.eq(TMetaField::getEntityCode, tMetaEntity.getEntityCode());
            tMetaFieldService.remove(lqw);
        }
        //根据json是否为空判断当前是新增还是修改 传入标识符
        tMetaEntityDTO.setCreateFlag(StringUtils.isEmpty(tMetaEntity.getEntityJson()));
        BeanUtils.copyProperties(tMetaEntity, tMetaEntityDTO);
        tMetaEntityDTO.setEntityJson(json);

        //解析元数据字段数据
        List<TMetaField> fieldList = gettMetaFieldList(gson, widgetList, entityCode);
        tMetaEntityDTO.setFieldList(fieldList);
        return tMetaEntityDTO;


    }


    private static List<TMetaField> gettMetaFieldList(Gson gson, JsonArray widgetList, Integer entityCode) {
        List<TMetaField> fieldList = new ArrayList<>();
        widgetList.forEach(item -> {
            JsonObject fromJson = gson.fromJson(item, JsonObject.class);
            // 获取options对象及其中的name值
            JsonObject fieldOptions = fromJson.getAsJsonObject("options");
            TMetaField tMetaField = new TMetaField();
            tMetaField.setFieldId("0000002-" + UUID.randomUUID().toString().replace("-", ""));
            tMetaField.setEntityCode(entityCode);
            tMetaField.setName(fieldOptions.get("name").getAsString());
            tMetaField.setLabel(fieldOptions.get("label").getAsString());
            tMetaField.setPhysicalName(fieldOptions.get("name").getAsString());
            tMetaField.setType(fromJson.get("type").getAsString());
            tMetaField.setDisplayOrder(0);
            //是否为空
            Integer nullable = null;
            if (ObjectUtils.isEmpty(fieldOptions.get("required"))) {
                nullable = 0;
            } else {
                nullable = "true".equals(fieldOptions.get("required").getAsString()) ? 1 : 0;
            }
            tMetaField.setNullable(nullable);
            tMetaField.setDisplayOrder(0);
            tMetaField.setCreatable(0);
            tMetaField.setUpdatable(0);
            //是否主键标识
            tMetaField.setIdFieldFlag(0);
            tMetaField.setNameFieldFlag(0);
            tMetaField.setMainDetailFieldFlag(0);
            tMetaField.setDefaultMemberOfListFlag(0);
            tMetaField.setReferTo("");
            fieldList.add(tMetaField);
        });
        return fieldList;
    }
}
